﻿using FluentAssertions;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NewRetail.Application.Components.Account.Model;
using NewRetail.Application.Components.Goods;
using NewRetail.Application.Components.Goods.Entity;
using NewRetail.Application.Components.Goods.Model;
using NewRetail.Application.Components.Platform.Entity;
using NewRetail.Application.Components.Warehouse.Entity;
using NewRetail.Application.Core;
using NewRetail.Application.Core.SingleStore;
using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
using Serilog;
using System;
using System.Drawing.Imaging;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;
using static System.Net.WebRequestMethods;

namespace NewRetail.Api.Controllers
{
    [NewRetailRoute("goods-info")]
    public class GoodsInfoController : BaseController<GoodsInfo, ProductPagingRequestDto>
    {
        private readonly IGoodsInfoService goodsInfoService;
        private readonly ISingleStoreService singleStoreService;

        public GoodsInfoController(IGoodsInfoService goodsInfoService, ISingleStoreService singleStoreService)
        {
            this.goodsInfoService = goodsInfoService;
            this.singleStoreService = singleStoreService;
        }

        [HttpPost("test-user")]
        public async Task<UserModel> CurrentLoginUser()
        {
            var data = await this.UserAccountService.GetCurrentLoginUser();
            return data;
        }

        public override async Task<ResponseEntity<GoodsInfo[]>> QueryAll()
        {
            var data = await base.QueryAll();
            data.ThrowIfNotSuccess();
            data.Data ??= Array.Empty<GoodsInfo>();

            data.Data = await this.goodsInfoService.AttachGoodsPrice(data.Data);

            return data;
        }

        protected override async Task<IQueryable<GoodsInfo>> OrderQueryPaging(IQueryable<GoodsInfo> query, ProductPagingRequestDto dto)
        {
            await Task.CompletedTask;

            query = query.OrderBy(x => x.No);

            return query;
        }

        [HttpPost("query-warehouse-goods-paging")]
        public async Task<ResponseEntity<PagedResultDto<GoodsInfo>>> QueryWarehouseGoodsPaging([FromBody] ProductPagingRequestDto dto)
        {
            dto.warehouseId.Should().NotBeNullOrEmpty();

            var data = await this.QueryPaging(dto);

            if (data.Data?.Items?.Any() ?? false)
            {
                var db = await this.Repo.GetDbContextAsync();
                var goodsIds = data.Data.Items.Select(x => x.Id).Distinct().ToArray();

                var warehouseGoods = await db.Set<WarehouseGoods>().AsNoTracking().Where(x => x.warehouseID == dto.warehouseId && goodsIds.Contains(x.goodsID)).ToArrayAsync();
                //会员价
                var goodsMemberPrices = await db.Set<GoodsMemberPrice>().AsNoTracking().Where(x => x.warehouseID == dto.warehouseId && goodsIds.Contains(x.goodsID)).ToArrayAsync();

                foreach (var m in data.Data.Items)
                {
                    var saleGoods = warehouseGoods.FirstOrDefault(x => x.warehouseID == dto.warehouseId && x.goodsID == m.Id);
                    if (saleGoods != null)
                    {
                        //添加会员价
                        saleGoods.GoodsMemberPrice = goodsMemberPrices.FirstOrDefault(x => x.warehouseID == dto.warehouseId && x.goodsID == m.Id);
                        m.price = saleGoods.price;
                        var saleGoodList = new System.Collections.Generic.List<WarehouseGoods>();
                        saleGoodList.Add(saleGoods);
                        m.GoodsPrices = saleGoodList;
                    }
                }
            }

            return data;
        }

        protected override async Task<IQueryable<GoodsInfo>> FilterQueryPaging(DbContext db, IQueryable<GoodsInfo> query, ProductPagingRequestDto dto)
        {
            await Task.CompletedTask;

            query = query.WhereIf(!string.IsNullOrWhiteSpace(dto.keyword), x =>
            x.goodsName.Contains(dto.keyword) ||
            x.No.Contains(dto.keyword) ||
            x.barCode.Contains(dto.keyword));

            if (!string.IsNullOrWhiteSpace(dto.name))
            {
                query = query.Where(x => x.goodsName.Contains(dto.name));
            }

            if (!string.IsNullOrWhiteSpace(dto.no))
            {
                query = query.Where(x => x.No.Contains(dto.no));
            }

            if (!string.IsNullOrWhiteSpace(dto.warehouseId))
            {
                var goodIds = db.Set<WarehouseGoods>().Where(x => x.warehouseID == dto.warehouseId).Select(x => x.goodsID);
                query = query.Where(x => goodIds.Contains(x.Id));
            }

            //过滤是否有销售数据。不传为全部显示，"1"为当天有销售的，"2"为当天未销售过的，"3"为从未销售过的
            if (!string.IsNullOrWhiteSpace(dto.showType))
            {
                var currDate = DateTime.Now;
                var goodIds = db.Set<PosSalesFlow>().Where(x => x.operateTime.Year == currDate.Year && x.operateTime.Month == currDate.Month && x.operateTime.Day == currDate.Day).Select(x => x.goodsID);
                if (dto.showType == "1")
                    query = query.Where(x => goodIds.Contains(x.Id));
                else if (dto.showType == "2")
                    query = query.Where(x => !goodIds.Contains(x.Id));
                else if (dto.showType == "3")
                {
                    var goodIdAlls = db.Set<PosSalesFlow>().Select(x => x.goodsID);
                    query = query.Where(x => !goodIdAlls.Contains(x.Id));
                }
            }
            //过滤出n天内没有销售过的记录
            int beforeDays = dto.noSaleDays ?? 0;
            if (beforeDays > 0)
            {
                var currDate = DateTime.Now;
                var bDays = currDate.AddDays(-beforeDays);
                var goodIds = db.Set<PosSalesFlow>().Where(x => x.operateTime > bDays).Select(x => x.goodsID);
                query = query.Where(x => goodIds != null && !goodIds.Contains(x.Id));
            }

            //单店权限
            string roleWarehouseId = this.singleStoreService.CurrentStore;
            if (!string.IsNullOrWhiteSpace(roleWarehouseId))
            {
                var goodCategoryIds = db.Set<GoodsCategory>().Where(x => x.warehouseID == roleWarehouseId).Select(x => x.Id);
                query = query.Where(x => goodCategoryIds.Contains(x.categoryID));
            }

            //退货时过滤指定供应商的商品
            if (!string.IsNullOrWhiteSpace(dto.supplierID) && dto.InOrOut != 1)
            {
                var goodIds = db.Set<InOutWarehousing>().Where(x => x.supplierID == dto.supplierID).Select(x => x.goodsID);
                query = query.Where(x => goodIds.Contains(x.Id));
                //var inOutWarehousings = db.Set<InOutWarehousing>().Where(x => x.supplierID == dto.supplierID)?.ToList();
                //if (inOutWarehousings.Count > 0)
                //{
                //    var goodIds = inOutWarehousings.Select(x => x.goodsID)?.ToList();
                //    query = query.Where(x => goodIds.Contains(x.Id));
                //}
            }
            //退货时候将库存小于等于0的商品过滤掉
            if (dto.InOrOut == (int)InOrOutEnum.OUT)
            {
                var goodIds = db.Set<WarehouseGoods>().Where(x => x.goodsNum > 0).Select(x => x.goodsID);
                query = query.Where(x => goodIds.Contains(x.Id));
            }
            //根据条件是否显示库存小于等于0的商品
            if (dto.showZeroWarehouseGoodsNum)
            {
                var goodIds = db.Set<WarehouseGoods>().Where(x => x.goodsNum > 0).Select(x => x.goodsID);
                query = query.Where(x => goodIds.Contains(x.Id));
            }
            query = query.WhereIf(!string.IsNullOrWhiteSpace(dto.categoryID), x => x.categoryID == dto.categoryID);

            //添加采购查询日期条件 add20240612
            if (dto.beginDate != null && dto.endDate != null)
            {
                var goodIds = db.Set<InOutWarehousing>().WhereIf(dto.beginDate != null, x => x.receiptDate >= dto.beginDate.Value).WhereIf(dto.endDate != null, x => x.receiptDate <= dto.endDate.Value).Select(x => x.goodsID);
                query = query.Where(x => goodIds != null && goodIds.Contains(x.Id));
            }

            return query;
        }

        protected override Task<GoodsInfo> BeforeUpdate(GoodsInfo entity, GoodsInfo data)
        {
            entity.goodsName = data.goodsName;
            entity.barCode = data.barCode;
            entity.categoryID = data.categoryID;
            entity.brand = data.brand;
            entity.specifications = data.specifications;
            entity.saleType = data.saleType;
            entity.metering = data.metering;
            entity.unit = data.unit;
            entity.originPlace = data.originPlace;
            entity.qualityTime = data.qualityTime;
            entity.price = data.price;
            entity.imgUrl = data.imgUrl;
            return base.BeforeUpdate(entity, data);
        }

        protected override async Task<GoodsInfo> BeforeInsertDataInitial(GoodsInfo data)
        {
            if (string.IsNullOrWhiteSpace(data.No))
            {
                data.No = await this.NoGeneratorService.GenerateGoodsNoAsync(data.categoryID);
            }
            if (string.IsNullOrWhiteSpace(data.barCode))
            {
                data.barCode = data.No;
            }

            return data;
        }

        protected override async Task<GoodsInfo> BeforeInsert(GoodsInfo data)
        {
            if (await this.Repo.AnyAsync(x => x.No == data.No))
            {
                throw new UserFriendlyException("编号已存在");
            }
            return data;
        }

        public override async Task<ResponseEntity<GoodsInfo>> Save([FromBody] GoodsInfo data)
        {
            var res = await this.SaveMultiple(new[] { data });
            res.ThrowIfNotSuccess();

            return new ResponseEntity<GoodsInfo>().SetData(data);
        }

        [HttpPost("save-multiple")]
        public async Task<ResponseEntity<GoodsInfo[]>> SaveMultiple([FromBody] GoodsInfo[] data)
        {
            data.Should().NotBeNullOrEmpty();
            using var uow = this.UnitOfWorkManager.Begin(requiresNew: true, isTransactional: true);
            try
            {
                var db = await this.Repo.GetDbContextAsync();
                var goodsSet = db.Set<GoodsInfo>();
                var priceSet = db.Set<WarehouseGoods>();
                var goodsMemberPriceSet = db.Set<GoodsMemberPrice>();

                foreach (var m in data)
                {
                    if (string.IsNullOrWhiteSpace(m.Id))
                    {
                        await this.BeforeInsertDataInitial(m);
                        this.EntityHelper.InitEntity(m);
                        await this.BeforeInsert(m);
                        goodsSet.Add(m);
                    }
                    else
                    {
                        var entity = await goodsSet.FirstOrDefaultAsync(x => x.Id == m.Id);
                        if (entity == null)
                        {
                            throw new UserFriendlyException("更新的对象不存在");
                        }
                        await this.BeforeUpdate(entity, m);
                        this.EntityHelper.SetUpdationInfo(entity);

                        ////删除门店价格
                        //var toDeleted = await priceSet.Where(x => x.goodsID == entity.Id).ToArrayAsync();
                        //if (toDeleted.Any())
                        //{
                        //    priceSet.RemoveRange(toDeleted);
                        //}

                        //删除会员价格
                        var toGoodsMemberPriceDeleted = await goodsMemberPriceSet.Where(x => x.goodsID == entity.Id).ToArrayAsync();
                        if (toGoodsMemberPriceDeleted.Any())
                        {
                            goodsMemberPriceSet.RemoveRange(toGoodsMemberPriceDeleted);
                        }
                    }

                    if (m.GoodsPrices?.Any() ?? false)
                    {
                        foreach (var p in m.GoodsPrices)
                        {
                            //如果没记录就插入
                            var warehouseGoodsEntity = await priceSet.Where(x => x.goodsID == m.Id && x.warehouseID == p.warehouseID).FirstOrDefaultAsync();
                            if (warehouseGoodsEntity == null)
                            {
                                this.EntityHelper.InitEntity(p);
                                p.goodsID = m.Id;

                                //#region add by cl 20230529
                                ////默认打折的
                                //p.isDiscount = true;
                                //#endregion

                                priceSet.Add(p);
                            }
                            else
                            {
                                //有记录更新价格
                                warehouseGoodsEntity.price = p.price;
                                this.EntityHelper.SetUpdationInfo(warehouseGoodsEntity);
                            }

                            //添加会员价
                            var goodsMemberPrice = p.GoodsMemberPrice;
                            if (goodsMemberPrice != null)
                            {
                                this.EntityHelper.InitEntity(goodsMemberPrice);
                                goodsMemberPrice.goodsID = m.Id;
                                goodsMemberPrice.warehouseID = p.warehouseID;
                                goodsMemberPriceSet.Add(goodsMemberPrice);
                            }
                        }
                    }
                }

                await db.SaveChangesAsync();

                await uow.CompleteAsync();
                return new ResponseEntity<GoodsInfo[]>().SetData(data);
            }
            catch
            {
                await uow.RollbackAsync();
                throw;
            }
        }

        public override async Task<ResponseEntity<GoodsInfo[]>> QueryByIds([FromBody] string[] ids)
        {
            var data = await base.QueryByIds(ids);
            data.ThrowIfNotSuccess();
            data.Data ??= Array.Empty<GoodsInfo>();

            data.Data = await this.goodsInfoService.AttachGoodsPrice(data.Data);
            data.Data = await this.goodsInfoService.AttachInOutWarehousing(data.Data);
            return data;
        }

        [HttpPost("query-by-ids-warehouseid")]
        public async Task<ResponseEntity<GoodsInfo[]>> QueryByIdsAndWarehouse([FromBody] GoodsChooseDto goodsChooseDto)
        {
            //this.logger.LogInformation("goodsChooseDto:" + JsonConvert.SerializeObject(goodsChooseDto));
            var data = await base.QueryByIds(goodsChooseDto.ids);
            data.ThrowIfNotSuccess();
            data.Data ??= Array.Empty<GoodsInfo>();

            data.Data = await this.goodsInfoService.AttachGoodsPrice(data.Data, goodsChooseDto.warehouseId);
            return data;
        }
        #region add by cl 20221112
        [HttpPost("query-comprehensive-paging")]
        public async Task<ResponseEntity<PagedResultDto<GoodsComprehensiveDto>>> QueryComprehensivePaging([FromBody] ProductPagingRequestDto dto)
        {
            var res = await base.QueryPaging(dto);

            var response = new PagedResultDto<GoodsComprehensiveDto>();
            if (res.Data?.Items?.Any() ?? false)
            {
                res.Data.Items = await this.goodsInfoService.AttachGoodsPrice(res.Data.Items.ToArray());
                res.Data.Items = await this.goodsInfoService.AttachInOutWarehousing(res.Data.Items.ToArray());
                res.Data.Items = await this.goodsInfoService.AttachGoodsCategory(res.Data.Items.ToArray());

                var goodsComprehensives = await this.goodsInfoService.AttachGoodsExtInfo(res.Data.Items.ToArray());
                //var goodsComprehensive = new List<GoodsComprehensiveDto>();
                //goodsComprehensive.TotalCount = res.Data.TotalCount;
                //foreach(var item in res.Data.Items)
                //{
                //    goodsComprehensive.Items.ToArray()
                //}

                response.TotalCount = res.Data.TotalCount;
                response.Items = goodsComprehensives;
            }
            var result = new ResponseEntity<PagedResultDto<GoodsComprehensiveDto>>().SetData(response);
            return result;
        }
        #endregion

        #region add by cl 20231114
        /// <summary>
        /// 手机掌售通项目的商品显示(仅供掌售通使用)
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("query-mobilecomprehensive-paging")]
        public async Task<ResponseEntity<PagedResultDto<GoodsMobileComprehensiveDto>>> QueryMobileComprehensivePaging([FromBody] ProductPagingRequestDto dto)
        {
            var res = await base.QueryPaging(dto);

            var response = new PagedResultDto<GoodsMobileComprehensiveDto>();
            if (res.Data?.Items?.Any() ?? false)
            {
                res.Data.Items = await this.goodsInfoService.AttachGoodsPrice(res.Data.Items.ToArray());
                res.Data.Items = await this.goodsInfoService.AttachInOutWarehousing(res.Data.Items.ToArray());
                res.Data.Items = await this.goodsInfoService.AttachGoodsCategory(res.Data.Items.ToArray());

                var goodsComprehensives = await this.goodsInfoService.AttachGoodsMobileExtInfo(res.Data.Items.ToArray());
             
                response.TotalCount = res.Data.TotalCount;
                response.Items = goodsComprehensives;
            }
            var result = new ResponseEntity<PagedResultDto<GoodsMobileComprehensiveDto>>().SetData(response);
            return result;
        }
        /// <summary>
        /// 根据商品id查询信息(仅供掌售通使用)
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        [HttpPost("query-by-ids-formobile")]
        public async Task<ResponseEntity<GoodsMobileDetDto[]>> QueryByIdsForMobile([FromBody] string[] ids)
        {
            var data = await base.QueryByIds(ids);
            data.ThrowIfNotSuccess();
            //data.Data ??= Array.Empty<GoodsInfo>();

            var response = new GoodsMobileDetDto[] { };
            if (data.Data?.Any() ?? false)
            {
                data.Data = await this.goodsInfoService.AttachGoodsPrice(data.Data);
                data.Data = await this.goodsInfoService.AttachInOutWarehousing(data.Data);
                var goodsMobileDets = await this.goodsInfoService.AttachGoodsMobileExtInfoByIds(data.Data.ToArray());

                response = goodsMobileDets;
            }
            var result = new ResponseEntity<GoodsMobileDetDto[]>().SetData(response);
            return result;
        }
        #endregion

        #region add by cl 20231214
        /// <summary>
        /// 手机掌售通项目的商品综合查询(仅供掌售通使用)
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("query-mobilegoodscomprehensive-paging")]
        public async Task<ResponseEntity<PagedResultDto<GoodsMobileComprehensiveDto>>> QueryMobileGoodsComprehensivePaging([FromBody] ProductPagingRequestDto dto)
        {
            var res = await base.QueryPaging(dto);

            var response = new PagedResultDto<GoodsMobileComprehensiveDto>();
            if (res.Data?.Items?.Any() ?? false)
            {
                res.Data.Items = await this.goodsInfoService.AttachGoodsPrice(res.Data.Items.ToArray());
                res.Data.Items = await this.goodsInfoService.AttachInOutWarehousing(res.Data.Items.ToArray());
                res.Data.Items = await this.goodsInfoService.AttachGoodsCategory(res.Data.Items.ToArray());

                var goodsComprehensives = await this.goodsInfoService.AttachGoodsMobileComprehensiveExtInfo(res.Data.Items.ToArray());

                response.TotalCount = res.Data.TotalCount;
                response.Items = goodsComprehensives;
            }
            var result = new ResponseEntity<PagedResultDto<GoodsMobileComprehensiveDto>>().SetData(response);
            return result;
        }
        #endregion

        #region add by cl 20240506
        [HttpPost("export-comprehensive-paging")]
        public async Task<IActionResult> ExportComprehensivePaging([FromBody] ProductPagingRequestDto dto)
        {
            try
            {
                var res = await QueryComprehensivePaging(dto);

                if (res.Data?.Items?.Any() ?? false)
                {
                    var result = await this.goodsInfoService.ExportComprehensiveGoodsInfo(res.Data.Items.ToArray());
                    var fName = string.Concat("商品综合信息");
                    if (result != null)
                        return File(result, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"{DateTime.Now.ToString("yyyyMMddHHmmss")}_{fName}.xlsx");
                }
            }
            catch (Exception e)
            {
                Log.Error(e.Message);
            }
            return BadRequest("商品综合信息导出失败！");
        }
        #endregion

        #region add by cl 20240614
        [HttpPost("query-comprehensive-colorsize-paging")]
        public async Task<ResponseEntity<PagedResultDto<GoodsTsInfoDto>>> QueryComprehensiveColorSizePaging([FromBody] ProductPagingColorSizeRequestDto inputDto)
        {
            //var res = await base.QueryPaging(dto);

            var response = new PagedResultDto<GoodsTsInfoDto>();
            var goodsComprehensives = await this.goodsInfoService.GetGoodsTsInfo(inputDto);
            response.TotalCount = goodsComprehensives.Count();
            int pageSize = inputDto.PageSize == 0 ? 100 : inputDto.PageSize, pageIndex = inputDto.Page == 0 ? 1 : inputDto.Page;
            //总页数
            var pageCount = (goodsComprehensives.Count() + pageSize - 1) / pageSize;
            goodsComprehensives = goodsComprehensives.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToArray();

            response.Items = goodsComprehensives;

            var result = new ResponseEntity<PagedResultDto<GoodsTsInfoDto>>().SetData(response);
            return result;
        }
        #endregion

        #region 更新是否新品的状态
        [HttpPost("update-isnewproduct-status")]
        public async Task<ResponseEntity<object>> UpdateIsNewProductStatus([FromBody] UpdateGoodsIsNewProductStatusDto[] dto)
        {
            await this.goodsInfoService.UpdateIsNewProductStatus(dto);

            return new ResponseEntity<object>().SetSuccess();
        }
        #endregion

        #region 下拉列表查询商品。 add 20241225
        [HttpPost("query-all-warehouse-goods")]
        public async Task<ResponseEntity<QueryAllGoodsByWarehouseResponse[]>> QueryAllGoodsByWarehouse([FromBody] QueryAllGoodsByWarehouseInputDto dto)
        {
            var res = await this.goodsInfoService.QueryAllGoodsByWarehouseBySql(dto);
            return new ResponseEntity<QueryAllGoodsByWarehouseResponse[]>().SetData(res.ToArray());
        }
        #endregion
    }
}
